package com.stellar.pay.core.convert;

import com.stellar.pay.core.entity.OrderQueryResultDTO;
import com.stellar.pay.core.entity.RefundResultDTO;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author Jqcc
 * @Version 1.0
 * @Data 2025/4/5
 * @Description : 转换微信支付结果到DTO
 */
public class ConvertWxResultToDTO {

    /**
     * 将微信支付订单查询结果转换为DTO
     *
     * @param transaction 微信支付订单查询结果
     * @return
     */
    public static OrderQueryResultDTO convertToOrderQueryResult(Transaction transaction) {
        OrderQueryResultDTO result = new OrderQueryResultDTO();

        // 基础字段映射
        result.setAppId(transaction.getAppid());
        result.setMchId(transaction.getMchid());
        result.setOutTradeNo(transaction.getOutTradeNo());
        result.setTransactionId(transaction.getTransactionId());
        result.setTradeType(transaction.getTradeType().name());
        result.setTradeState(transaction.getTradeState().name());
        result.setTradeStateDesc(transaction.getTradeStateDesc());
        result.setSuccessTime(parseDateTime(transaction.getSuccessTime()));
        result.setAttach(transaction.getAttach());
        result.setBankType(transaction.getBankType());

        // 处理嵌套对象
        if (transaction.getAmount() != null) {
            OrderQueryResultDTO.AmountDTO amountDTO = new OrderQueryResultDTO.AmountDTO();
            amountDTO.setTotal(transaction.getAmount().getTotal());
            amountDTO.setCurrency(transaction.getAmount().getCurrency());
            result.setAmount(amountDTO);
        }

        if (transaction.getPayer() != null) {
            OrderQueryResultDTO.PayerDTO payerDTO = new OrderQueryResultDTO.PayerDTO();
            payerDTO.setOpenid(transaction.getPayer().getOpenid());
            result.setPayer(payerDTO);
        }

        // 处理优惠信息（示例仅映射部分字段）
        if (transaction.getPromotionDetail() != null) {
            List<OrderQueryResultDTO.PromotionDetailDTO> promotionDetails =
                    transaction.getPromotionDetail().stream().map(detail -> {
                        OrderQueryResultDTO.PromotionDetailDTO dto = new OrderQueryResultDTO.PromotionDetailDTO();
                        dto.setCouponId(detail.getCouponId());
                        dto.setName(detail.getName());
                        dto.setAmount(detail.getAmount());
                        return dto;
                    }).collect(Collectors.toList());
            result.setPromotionDetails(promotionDetails);
        }

        return result;
    }


    /**
     * 将微信退款结果转换为DTO
     *
     * @param refund 微信退款结果
     * @return
     */
    public static RefundResultDTO convertToRefundResult(Refund refund) {
        if (refund == null) {
            return null;
        }

        RefundResultDTO result = new RefundResultDTO();

        // 基础字段
        result.setRefundId(refund.getRefundId());
        result.setOutRefundNo(refund.getOutRefundNo());
        result.setTransactionId(refund.getTransactionId());
        result.setOutTradeNo(refund.getOutTradeNo());

        // 枚举转换
        result.setChannel(refund.getChannel() != null ? refund.getChannel().name() : null);
        result.setUserReceivedAccount(refund.getUserReceivedAccount());
        result.setStatus(refund.getStatus() != null ? refund.getStatus().name() : null);
        result.setFundsAccount(refund.getFundsAccount() != null ? refund.getFundsAccount().name() : null);

        // 时间处理
        result.setSuccessTime(parseDateTime(refund.getSuccessTime()));
        result.setCreateTime(parseDateTime(refund.getCreateTime()));

        // 处理金额信息
        if (refund.getAmount() != null) {
            RefundResultDTO.RefundAmountDTO amountDTO = new RefundResultDTO.RefundAmountDTO();
            amountDTO.setTotal(refund.getAmount().getTotal());
            amountDTO.setRefund(refund.getAmount().getRefund());
            amountDTO.setCurrency(refund.getAmount().getCurrency());
            amountDTO.setPayerTotal(refund.getAmount().getPayerTotal());
            amountDTO.setPayerRefund(refund.getAmount().getPayerRefund());
            amountDTO.setDiscountRefund(refund.getAmount().getDiscountRefund() != null ?
                    refund.getAmount().getDiscountRefund() : 0L);

            // 处理资金来源
            List<RefundResultDTO.FundSourceDTO> fromList = new ArrayList<>();
            if (refund.getAmount().getFrom() != null) {
                fromList = refund.getAmount().getFrom().stream()
                        .filter(Objects::nonNull)
                        .map(source -> {
                            RefundResultDTO.FundSourceDTO dto = new RefundResultDTO.FundSourceDTO();
                            dto.setAccount(source.getAccount() != null ? source.getAccount().name() : null);
                            dto.setAmount(source.getAmount());
                            return dto;
                        })
                        .collect(Collectors.toList());
            }
            amountDTO.setFrom(fromList);

            result.setAmount(amountDTO);
        }

        // 处理优惠信息
        List<RefundResultDTO.PromotionDetailDTO> promotionDetails = new ArrayList<>();
        if (refund.getPromotionDetail() != null) {
            promotionDetails = refund.getPromotionDetail().stream()
                    .filter(Objects::nonNull)
                    .map(promo -> {
                        RefundResultDTO.PromotionDetailDTO dto = new RefundResultDTO.PromotionDetailDTO();
                        dto.setPromotionId(promo.getPromotionId());
                        dto.setType(promo.getType() != null ? promo.getType().name() : null);
                        dto.setAmount(promo.getAmount());
                        dto.setRefundAmount(promo.getRefundAmount());

                        // 处理商品详情
                        List<RefundResultDTO.GoodsDetailDTO> goodsDetails = new ArrayList<>();
                        if (promo.getGoodsDetail() != null) {
                            goodsDetails = promo.getGoodsDetail().stream()
                                    .filter(Objects::nonNull)
                                    .map(goods -> {
                                        RefundResultDTO.GoodsDetailDTO goodsDto = new RefundResultDTO.GoodsDetailDTO();
                                        goodsDto.setGoodsId(goods.getMerchantGoodsId());
                                        goodsDto.setGoodsName(goods.getGoodsName());
                                        goodsDto.setUnitPrice(goods.getUnitPrice());
                                        goodsDto.setRefundAmount(goods.getRefundAmount());
                                        goodsDto.setRefundQuantity(goods.getRefundQuantity());
                                        return goodsDto;
                                    })
                                    .collect(Collectors.toList());
                        }
                        dto.setGoodsDetails(goodsDetails);
                        return dto;
                    })
                    .collect(Collectors.toList());
        }
        result.setPromotionDetails(promotionDetails);

        return result;
    }


    /**
     * 将微信订单查询结果转换为DTO （仅当订单状态为已关闭才会用该方法转换）
     *
     * @param transaction 微信订单查询结果
     * @return
     */
    public static OrderQueryResultDTO convertClosedOrderToDTO(Transaction transaction) {
        OrderQueryResultDTO result = new OrderQueryResultDTO();

        // 基础字段映射
        result.setAppId(transaction.getAppid());
        result.setMchId(transaction.getMchid());
        result.setOutTradeNo(transaction.getOutTradeNo());
        result.setTradeState(transaction.getTradeState().name());
        result.setTradeStateDesc(transaction.getTradeStateDesc());
        result.setAttach(transaction.getAttach());

        // 关闭订单特有的处理
        result.setTradeType(transaction.getTradeType() != null ? transaction.getTradeType().name() : null);

        // 金额信息
        if (transaction.getAmount() != null) {
            OrderQueryResultDTO.AmountDTO amountDTO = new OrderQueryResultDTO.AmountDTO();
            amountDTO.setTotal(transaction.getAmount().getTotal());
            amountDTO.setCurrency(transaction.getAmount().getCurrency());
            result.setAmount(amountDTO);
        }

        return result;
    }


    // 处理微信的ISO8601时间格式
    private static LocalDateTime parseDateTime(String timeStr) {
        if (StringUtils.isEmpty(timeStr)) {
            return null;
        }
        try {
            return LocalDateTime.parse(timeStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 创建未找到退款记录的退款结果
     *
     * @param outRefundNo 退款单号
     * @return
     */
    public static RefundResultDTO createNotFoundRefundResult(String outRefundNo) {
        RefundResultDTO result = new RefundResultDTO();
        result.setOutRefundNo(outRefundNo);
        result.setStatus("NOT_FOUND");
        result.setErrorMessage("退款单不存在");
        return result;
    }

    /**
     * 创建退款失败的退款结果
     *
     * @param outRefundNo  退款单号
     * @param errorMessage 错误信息
     * @return
     */
    public static RefundResultDTO createErrorRefundResult(String outRefundNo, String errorMessage) {
        RefundResultDTO result = new RefundResultDTO();
        result.setOutRefundNo(outRefundNo);
        result.setStatus("ERROR");
        result.setErrorMessage(errorMessage);
        return result;
    }
}
